﻿package code {
	
	import flash.display.MovieClip;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import com.danielfreeman.extendedMadness.*;
	import com.danielfreeman.madcomponents.*;
	import flash.media.StageWebView;
	import flash.display.StageOrientation;
	import flash.geom.Rectangle;
	
	public class Document extends MovieClip {
		
		/*************** XML DATA ***************/
		
		// Data for LEFT SCROLL List
		protected static const LEFT_DATA:XML = <data>
											<feed label="Associated Press" url="http://hosted.ap.org/lineups/WORLDHEADS.rss?SITE=AP&SECTION=HOME"/>
					
											<feed label="Reuters" url="http://feeds.reuters.com/reuters/worldNews?format=xml"/>
											
											<feed label="United Press Int'l" url="http://pheed.upi.com/news/top_news_rss"/>
										</data>;
										
		// Data for RIGHT SCROLL List
		protected static const RIGHT_DATA:XML = <data>
													<Loading label="Loading..."/>
												</data>;
		
		// Left half of our custom Split View
		protected static const LEFT_SCROLL:XML =<horizontal alignH="left" heights="60%" > 
														<list alignH="left" id="leftScroll">
															{LEFT_DATA}
														</list>
												</horizontal>;
		
		// Right half of our custom Split View
		protected static const RIGHT_SCROLL:XML = <vertical alignH="right">
													<list id="rightScroll">
														{RIGHT_DATA}
													</list>
												  </vertical>;
												
		// The entire layout, this makes it easier to draw the whole screen
		protected static const LAYOUT:XML = <navigation id="navigation" rightButton="Full Map" title="GeoNews" >
												<columns widths="26%,74%">			
													{LEFT_SCROLL}
													{RIGHT_SCROLL}
												</columns>
											</navigation>;
		
		/*************** END XML ****************/
		
		
		/***************** VARS *****************/
		
		// Access for Left Scroll List
		protected var leftScroll:UIList;
		
		// Access for Right Scroll List
		protected var rightScroll:UIList;
		
		// Lower-Left "mini-map"
		protected var miniMapView:StageWebView;
		
		// Right web view
		protected var webView:StageWebView;
		
		protected var activity:StageWebView;
		
		protected var navBar:UINavigationBar;
		protected var nav:UINavigation;
		
		// Current item for lists
		protected var currentItem:int = 0;
		protected var itemArray:Array;
		protected var origLeftList;
		protected var aggregateArray:Array;
		protected var fetcher:Fetcher;
		protected var curLocation:String;
		
		protected var fetchArray:Array;
		protected static var aggregateCount:int = 3;
		protected var isLeftFeeds:Boolean = true;
		
		protected var fullMap:Boolean = true;
		
		private var jsCommand:String;
		private var backBtn:UIButton;
		
		/**************** END VARS **************/
		
		
		/**************** CONSTS ****************/
		protected const MAP_URL:String = "http://people.rit.edu/~ajz9310/x-mobile/map.html";
		protected const ACT_URL:String = "http://people.rit.edu/~ajz9310/x-mobile/activity.html";
		/************** END CONSTS **************/
		
		
		
		// CONSTRUCTOR
		public function Document() {
			// constructor code
			//trace(this + "created");
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			// Create UI from XML
			UIe.createInWindow(this,LAYOUT);
			
			nav = UINavigation(UI.findViewById("navigation"));
			navBar = UINavigationBar(nav.navigationBar);
			navBar.height = stage.stageHeight * .08;
			navBar.rightButton.addEventListener(UIButton.CLICKED, onMenuClicked);
			backBtn = new UIButton(navBar, 8, 5, '<font size="14">menu</font>', 0xAA7777, new <uint>[], true);
			backBtn.text = "Feed List";
			backBtn.addEventListener(UIButton.CLICKED, onBackClicked);

			leftScroll = UIList(UI.findViewById("leftScroll"));
			leftScroll.addEventListener(UIList.CLICKED, onLeftListClicked);
			
			rightScroll = UIList(UI.findViewById("rightScroll"));
			rightScroll.addEventListener(UIList.CLICKED, onRightListClicked);

			drawSplitViewBreak();
			
			miniMapView= new StageWebView();
			miniMapView.stage = this.stage;
			
			webView = new StageWebView();
			webView.stage = this.stage;
			webView.addEventListener(Event.COMPLETE, webViewLoaded);
			
			activity = new StageWebView();
			activity.stage = this.stage;
			
			showMiniMap(true);
			origLeftList = leftScroll.data;
			loadAggregate();
			
		}
		
		
/**************************** CALLBACKS ************************************/
/***************************************************************************/
		
		//function to swap the lists back to the default views
		private function onBackClicked(e:Event)
		{
			showWebView(false);
			fullMap = false;
			leftScroll.data = origLeftList;
			isLeftFeeds = true;
		}
		
		// Event handler for Left List item being clicked
		private function onLeftListClicked(e:Event):void
		{
			showActivity(true);
			showWebView(false);
			//trace("onLeftListClicked e.target=" + e.target);
			if(isLeftFeeds)
			{
			// This code is for when the left list is populated with feeds
			var targetIndex:int = e.target.index;	
			var targetXML:XML = e.target.xml;
			
			var urlToDownload:String = targetXML.data.feed[targetIndex].@url;
			
			fetcher = new Fetcher();
			
			//Set up event listeners with weak references
			fetcher.addEventListener(CustomEvent.LOAD_COMPLETE,onXMLLoaded,false,0,true);
			fetcher.addEventListener(CustomEvent.LOAD_ERROR,onXMLLoadError,false,0,true);
			fetcher.loadXML(urlToDownload);
			
			}else
			{
				var rowClicked:int = e.target.index;
				
				currentItem = rowClicked;
				
				if(! (itemArray[currentItem] && itemArray[currentItem].url)){
					displayMessage("Could not load article!");
					showActivity(false);
					// bail!
					return;
				}
				
				// get url of article from itemArray
				var url:String = itemArray[currentItem].url;
				
				// Populate left list with articles from item array
				leftScroll.data = shortenTitles(itemArray);
				curLocation = stripTags(String(itemArray[currentItem].description).split("(")[0]);
				showLocation(miniMapView);
		
				webView.loadURL(url);
			}
		}
		
		// Event handler for Menu Button being clicked
		private function onMenuClicked(e:Event){
			if(fullMap)
			{
				e.currentTarget.text = "Article";
				showLocation(webView);
			}else{
				e.currentTarget.text = "Full Map";
				showWebView(false);
				showActivity(true);
				webView.loadURL(itemArray[currentItem].url);
			}
			
			fullMap = !fullMap;
		}
		
		// Event handler for the MiniMap being loaded
		private function onMiniMapLoaded(e:Event):void
		{
			if(e.currentTarget.title == "GeoNews"){
				e.currentTarget.loadURL(jsCommand);
			}else{
				showWebView(true);
			}
		}
		
		// Event handler for Right List item being clicked
		private function onRightListClicked(e:Event):void
		{
			showActivity(true);

			var rowClicked:int = e.target.index;
			
			currentItem = rowClicked;
			
			if(! (itemArray[currentItem] && itemArray[currentItem].url)){
				displayMessage("Could not load article!");
				// bail!
				showActivity(false);
				return;
			}
			
			// get url of article from itemArray
			var url:String = itemArray[currentItem].url;
			// Populate left list with articles from item array
			origLeftList = leftScroll.data;
			leftScroll.data = shortenTitles(itemArray);
			isLeftFeeds = false;
			showLocation(miniMapView);
			webView.loadURL(url);
		}
		
		// Event handler for XML Loading successfully
		private function onXMLLoaded(e:CustomEvent,aggregate:Boolean = false){
			var xml:XML = new XML(e.data);
			
			// XML parsing
			var feedDescription:String = xml.channel[0].description[0].text();
			
			// get articles
			itemArray = new Array();
			
			//get XMLList
			var allItems:XMLList = xml.channel[0].item;
			
			// Loop through items
			for each(var item:XML in allItems){
				// create a data object for each item
				var itemData:Object = new Object();
				
				// set properties of this object
				itemData.label = '<font size="14">' + stripTags(item.title[0].text()) + '</font>';
				itemData.url = item.link[0].text();
				itemData.description = item.description[0].text();
				
				// AP RSS does not have pubDate, check to see if its undefined
				if(item.pubDate != undefined){
					itemData.pubDate = item.pubDate[0].text();
				}
				
				// add object to our item array
				itemArray.push(itemData);
			}
			
			showActivity(false);

			if(!aggregate){
				//Assign array to the master list of articles
				rightScroll.data = itemArray;
				// Clean up
				fetcher.destroy();
				fetcher = null;
			}else{
				aggregateArray = aggregateArray.concat(itemArray);
				if(--aggregateCount == 0){
					/***** NEED TO CLEAN UP FETCHER ARRAY ******/
					for each (var fetcher:Fetcher in fetchArray) {
						fetcher.destroy();
						fetcher = null;
					}
					fetchArray = null;
					rightScroll.data = aggregateArray;
					itemArray = aggregateArray;
				}
			}
			showLocation(miniMapView);
		}
		
		// Event handler for XML loading with Error
		private function onXMLLoadError(e:CustomEvent, aggregate:Boolean = false){
			//trace("onXMLLoadError");
			displayMessage("Could not load feed!");
			if(aggregate && --aggregateCount == 0){
					rightScroll.data = aggregateArray;
			}
			fetcher = null;
		}
		
		// Event handler for WebView loading a URL
		private function webViewLoaded(e:Event)
		{
			showActivity(false);
			showWebView(true);
		}
		
		
		
/**************************** HELPER FUNCTIONS *****************************/
/***************************************************************************/
		
		// Function to display an alert window
		private function displayMessage(msg:String){
			new AlertMessage(this, msg, "Ok");
		}
				
		// Function to draw the vertical SplitView break
		private function drawSplitViewBreak()
		{
			graphics.beginFill(0x9E9E9E);
			graphics.drawRect(stage.stageWidth * .26,0,3,stage.stageHeight);
			graphics.endFill();
		}
		
		// Function to load aggregate articles
		private function loadAggregate()
		{
			showActivity(true);
			fetchArray = new Array();
			//trace("loading all articles!");
			aggregateArray = new Array();
			for(var i:Number = 0; i < 3; i++)
			{
				//var urlToDownload:String = LEFT_DATA.data.feed[targetIndex].@url;
				//trace("URL: " + leftScroll.xml.data.feed[i].@url);
				fetchArray.push(new Fetcher());
				Fetcher(fetchArray[i]).addEventListener(CustomEvent.LOAD_COMPLETE,function(e:CustomEvent) : void {
                  onXMLLoaded(e,true);},false,0,true);
				
				Fetcher(fetchArray[i]).addEventListener(CustomEvent.LOAD_ERROR,function(e:CustomEvent) : void {
                  onXMLLoadError(e,true);},false,0,true);
				Fetcher(fetchArray[i]).loadXML(leftScroll.xml.data.feed[i].@url);
			}
		}
		
		// Function to shorten the Article titles to 40 characters and add an ellipsis
		private function shortenTitles(articleArray:Array):Array
		{
			var tempArray:Array = new Array();
			for each(var item:Object in articleArray){
				item.label = stripTags(item.label);
				item.label = '<font size="14">' + item.label.slice(0,30) + "..." + '</font>';
				tempArray.push(item);
			}
			return tempArray;
		}
		
		// Function to show the activity indicator
		// Uses a StageWebView to display an animated Activity .gif
		private function showActivity(shouldShow:Boolean)
		{
			if(shouldShow)
			{
				activity.viewPort = new Rectangle(stage.stageWidth * .265,stage.stageHeight * .08,stage.stageWidth - stage.stageWidth * .265,stage.stageHeight-stage.stageHeight * .08);
				activity.loadURL(ACT_URL);
			}else
			{
				activity.viewPort = new Rectangle(0,0,0,0);
			}
		}
		
		// Function to show Location
		private function showLocation(view:StageWebView):void
		{
			curLocation = stripTags(String(itemArray[currentItem].description).split("(")[0]);
			jsCommand = "javascript:findLocation(" +
									'\"' + curLocation +'\"' + ")";
									
			// Load map again to ensure it exists
			view.loadURL(MAP_URL);
			view.addEventListener(Event.COMPLETE,onMiniMapLoaded);
		}
		
		// Function to show/hide the MiniMap
		private function showMiniMap(shouldShow:Boolean)
		{
			if(shouldShow)
			{
				miniMapView.viewPort = new Rectangle(0,stage.stageHeight * .60,stage.stageWidth * .26,stage.stageHeight * .40);
				miniMapView.loadURL(MAP_URL);
			}else{
				miniMapView.viewPort = new Rectangle(0,0,0,0);
			}
		}
		
		// Function to show/hide the WebView
		private function showWebView(shouldShow:Boolean)
		{
			if(shouldShow)
			{
				webView.viewPort = new Rectangle(stage.stageWidth * .265,stage.stageHeight * .08,stage.stageWidth - stage.stageWidth * .265,stage.stageHeight-stage.stageHeight * .08);
			}else{
				webView.viewPort = new Rectangle(0,0,0,0);
			}
		}
		
		// Helper function to strip HTML tags from the description
		function stripTags(string):String {
			while ((string.indexOf("<")) != -1) {
				string = string.split(string.substr(string.indexOf("<"), string.indexOf(">")-string.indexOf("<")+1)).join("");
			}
			return string;
		}
		
	}
	
}
